<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"wan-lei8.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="1.策略模式 ​    假设有这样的业务场景，大数据系统把文件推送过来，根据不同类型采取不同的解析方式。">
<meta property="og:type" content="article">
<meta property="og:title" content="常用的几种设计模式">
<meta property="og:url" content="https://wan-lei8.gitee.io/2020/12/29/%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E7%A7%8D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/index.html">
<meta property="og:site_name" content="程序员西桐">
<meta property="og:description" content="1.策略模式 ​    假设有这样的业务场景，大数据系统把文件推送过来，根据不同类型采取不同的解析方式。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="c:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20211229191008123.png">
<meta property="og:image" content="c:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20211229191201437.png">
<meta property="article:published_time" content="2020-12-29T08:48:55.000Z">
<meta property="article:modified_time" content="2021-12-29T11:18:51.064Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="c:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20211229191008123.png">

<link rel="canonical" href="https://wan-lei8.gitee.io/2020/12/29/%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E7%A7%8D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>常用的几种设计模式 | 程序员西桐</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">程序员西桐</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">但行好事，莫问前程</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2020/12/29/%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E7%A7%8D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          常用的几种设计模式
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-12-29 16:48:55" itemprop="dateCreated datePublished" datetime="2020-12-29T16:48:55+08:00">2020-12-29</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-12-29 19:18:51" itemprop="dateModified" datetime="2021-12-29T19:18:51+08:00">2021-12-29</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <blockquote>
<h4 id="1-策略模式"><a href="#1-策略模式" class="headerlink" title="1.策略模式"></a><strong>1.策略模式</strong></h4></blockquote>
<p>​    假设有这样的业务场景，大数据系统把文件推送过来，根据不同类型采取<strong>不同的解析</strong>方式。</p>
<span id="more"></span>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(type==<span class="string">&quot;A&quot;</span>)&#123;</span><br><span class="line">   <span class="comment">//按照A格式解析</span></span><br><span class="line"> </span><br><span class="line">&#125;<span class="keyword">else</span> <span class="keyword">if</span>(type==<span class="string">&quot;B&quot;</span>)&#123;</span><br><span class="line">    <span class="comment">//按B格式解析</span></span><br><span class="line">&#125;<span class="keyword">else</span>&#123;</span><br><span class="line">    <span class="comment">//按照默认格式解析</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这个代码可能会存在哪些<strong>问题呢</strong>？</p>
<ul>
<li>如果分支变多，这里的代码就会变得<strong>臃肿，难以维护，可读性低</strong>。</li>
<li>如果你需要接入一种新的解析类型，那只能在<strong>原有代码上修改</strong>。</li>
</ul>
<p>说得专业一点的话，就是以上代码，违背了面向对象编程的<strong>开闭原则</strong>以及<strong>单一原则</strong>。</p>
<ul>
<li><strong>开闭原则</strong>（对于扩展是开放的，但是对于修改是封闭的）：增加或者删除某个逻辑，都需要修改到原来代码</li>
<li><strong>单一原则</strong>（规定一个类应该只有一个发生变化的原因）：修改任何类型的分支逻辑代码，都需要改动当前类的代码。</li>
</ul>
<p>如果你的代码就是酱紫：有多个<code>if...else</code>等条件分支，并且每个条件分支，可以封装起来替换的，我们就可以使用<strong>策略模式</strong>来优化。</p>
<h3 id="1-2-策略模式定义"><a href="#1-2-策略模式定义" class="headerlink" title="1.2 策略模式定义"></a>1.2 策略模式定义</h3><p><strong>策略模式</strong>定义了算法族，分别封装起来，让它们之间可以相互替换，此模式让算法的变化独立于使用算法的的客户。这个策略模式的定义是不是有点抽象呢？那我们来看点通俗易懂的比喻：</p>
<blockquote>
<p>假设你跟不同性格类型的小姐姐约会，要用不同的策略，有的请电影比较好，有的则去吃小吃效果不错，有的去逛街买买买最合适。当然，目的都是为了得到小姐姐的芳心，请看电影、吃小吃、逛街就是不同的策略。</p>
</blockquote>
<p>策略模式针对一组算法，将每一个算法封装到具有共同接口的独立的类中，从而使得它们可以相互替换。</p>
<h3 id="1-3-策略模式使用"><a href="#1-3-策略模式使用" class="headerlink" title="1.3 策略模式使用"></a>1.3 策略模式使用</h3><p>策略模式怎么使用呢？酱紫实现的：</p>
<ul>
<li>一个接口或者抽象类，里面两个方法（一个方法匹配类型，一个可替换的逻辑实现方法）</li>
<li>不同策略的差异化实现(就是说，不同策略的实现类)</li>
<li>使用策略模式</li>
</ul>
<h4 id="1-3-1-一个接口，两个方法"><a href="#1-3-1-一个接口，两个方法" class="headerlink" title="1.3.1 一个接口，两个方法"></a>1.3.1 一个接口，两个方法</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">IFileStrategy</span> </span>&#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//属于哪种文件解析类型</span></span><br><span class="line">    <span class="function">FileTypeResolveEnum <span class="title">gainFileType</span><span class="params">()</span></span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//封装的公用算法（具体的解析方法）</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">resolve</span><span class="params">(Object objectparam)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="1-3-2-不同策略的差异化实现"><a href="#1-3-2-不同策略的差异化实现" class="headerlink" title="1.3.2 不同策略的差异化实现"></a>1.3.2 不同策略的差异化实现</h4><p>A 类型策略具体实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AFileResolve</span> <span class="keyword">implements</span> <span class="title">IFileStrategy</span> </span>&#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> FileTypeResolveEnum <span class="title">gainFileType</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> FileTypeResolveEnum.File_A_RESOLVE;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">resolve</span><span class="params">(Object objectparam)</span> </span>&#123;</span><br><span class="line">      logger.info(<span class="string">&quot;A 类型解析文件，参数：&#123;&#125;&quot;</span>,objectparam);</span><br><span class="line">      <span class="comment">//A类型解析具体逻辑</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>B 类型策略具体实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BFileResolve</span> <span class="keyword">implements</span> <span class="title">IFileStrategy</span> </span>&#123;</span><br><span class="line">   </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> FileTypeResolveEnum <span class="title">gainFileType</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> FileTypeResolveEnum.File_B_RESOLVE;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">resolve</span><span class="params">(Object objectparam)</span> </span>&#123;</span><br><span class="line">      logger.info(<span class="string">&quot;B 类型解析文件，参数：&#123;&#125;&quot;</span>,objectparam);</span><br><span class="line">      <span class="comment">//B类型解析具体逻辑</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>默认类型策略具体实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DefaultFileResolve</span> <span class="keyword">implements</span> <span class="title">IFileStrategy</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> FileTypeResolveEnum <span class="title">gainFileType</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> FileTypeResolveEnum.File_DEFAULT_RESOLVE;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">resolve</span><span class="params">(Object objectparam)</span> </span>&#123;</span><br><span class="line">      logger.info(<span class="string">&quot;默认类型解析文件，参数：&#123;&#125;&quot;</span>,objectparam);</span><br><span class="line">      <span class="comment">//默认类型解析具体逻辑</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="1-3-3-使用策略模式"><a href="#1-3-3-使用策略模式" class="headerlink" title="1.3.3 使用策略模式"></a>1.3.3 使用策略模式</h4><p>如何使用呢？我们借助<code>spring</code>的生命周期，使用<code>ApplicationContextAware</code>接口，把对用的策略，初始化到<code>map</code>里面。然后对外提供<code>resolveFile</code>方法即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StrategyUseService</span> <span class="keyword">implements</span> <span class="title">ApplicationContextAware</span></span>&#123;</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line">    <span class="keyword">private</span> Map&lt;FileTypeResolveEnum, IFileStrategy&gt; iFileStrategyMap = <span class="keyword">new</span> ConcurrentHashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">resolveFile</span><span class="params">(FileTypeResolveEnum fileTypeResolveEnum, Object objectParam)</span> </span>&#123;</span><br><span class="line">        IFileStrategy iFileStrategy = iFileStrategyMap.get(fileTypeResolveEnum);</span><br><span class="line">        <span class="keyword">if</span> (iFileStrategy != <span class="keyword">null</span>) &#123;</span><br><span class="line">            iFileStrategy.resolve(objectParam);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//把不同策略放到map</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setApplicationContext</span><span class="params">(ApplicationContext applicationContext)</span> <span class="keyword">throws</span> BeansException </span>&#123;</span><br><span class="line">        Map&lt;String, IFileStrategy&gt; tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);</span><br><span class="line">        tmepMap.values().forEach(strategyService -&gt; iFileStrategyMap.put(strategyService.gainFileType(), strategyService));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<h4 id="责任链模式"><a href="#责任链模式" class="headerlink" title="责任链模式"></a>责任链模式</h4></blockquote>
<h3 id="2-1-业务场景"><a href="#2-1-业务场景" class="headerlink" title="2.1 业务场景"></a>2.1 业务场景</h3><p>我们来看一个常见的业务场景，下订单。下订单接口，基本的逻辑，一般有参数非空校验、安全校验、黑名单校验、规则拦截等等。很多伙伴会使用异常来实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Order</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">checkNullParam</span><span class="params">(Object param)</span></span>&#123;</span><br><span class="line">      <span class="comment">//参数非空校验</span></span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">checkSecurity</span><span class="params">()</span></span>&#123;</span><br><span class="line">      <span class="comment">//安全校验</span></span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">checkBackList</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//黑名单校验</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">checkRule</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//规则拦截</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Order order= <span class="keyword">new</span> Order();</span><br><span class="line">        <span class="keyword">try</span>&#123;</span><br><span class="line">            order.checkNullParam();</span><br><span class="line">            order.checkSecurity ();</span><br><span class="line">            order.checkBackList();</span><br><span class="line">            order2.checkRule();</span><br><span class="line">            System.out.println(<span class="string">&quot;order success&quot;</span>);</span><br><span class="line">        &#125;<span class="keyword">catch</span> (RuntimeException e)&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;order fail&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这段代码使用了<strong>异常</strong>来做逻辑条件判断，如果后续逻辑越来越复杂的话，会出现一些问题：如异常只能返回异常信息，不能返回更多的字段，这时候需要<strong>自定义异常类</strong>。</p>
<p>并且，阿里开发手册规定：<strong>禁止用异常做逻辑判断</strong>。</p>
<blockquote>
<p>【强制】 异常不要用来做流程控制，条件控制。说明：异常设计的初衷是解决程序运行中的各种意外情况，且异常的处理效率比条件判断方式要低很多。</p>
</blockquote>
<p>如何优化这段代码呢？可以考虑<strong>责任链模式</strong></p>
<h3 id="2-2-责任链模式定义"><a href="#2-2-责任链模式定义" class="headerlink" title="2.2 责任链模式定义"></a>2.2 责任链模式定义</h3><p>当你想要让一个<strong>以上的对象</strong>有机会能够处理某个请求的时候，就使用<strong>责任链模式</strong>。</p>
<blockquote>
<p>责任链模式为请求创建了一个接收者对象的链。执行链上有多个对象节点，每个对象节点都有机会（条件匹配）处理请求事务，如果某个对象节点处理完了，就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。这种模式给予请求的类型，对请求的发送者和接收者进行解耦。</p>
</blockquote>
<p>责任链模式实际上是一种处理请求的模式，它让多个处理器（对象节点）都有机会处理该请求，直到其中某个处理成功为止。责任链模式把多个处理器串成链，然后让请求在链上传递：</p>
<img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211229191008123.png" alt="image-20211229191008123" style="zoom:80%;" />

<h3 id="2-3-责任链模式使用"><a href="#2-3-责任链模式使用" class="headerlink" title="2.3 责任链模式使用"></a>2.3 责任链模式使用</h3><p>责任链模式怎么使用呢？</p>
<ul>
<li>一个接口或者抽象类</li>
<li>每个对象差异化处理</li>
<li>对象链（数组）初始化（连起来）</li>
</ul>
<h4 id="2-3-1-一个接口或者抽象类"><a href="#2-3-1-一个接口或者抽象类" class="headerlink" title="2.3.1 一个接口或者抽象类"></a>2.3.1 一个接口或者抽象类</h4><p>这个接口或者抽象类，需要：</p>
<ul>
<li>有一个指向责任下一个对象的属性</li>
<li>一个设置下一个对象的set方法</li>
<li>给子类对象差异化实现的方法（如以下代码的doFilter方法）</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">AbstractHandler</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//责任链中的下一个对象</span></span><br><span class="line">    <span class="keyword">private</span> AbstractHandler nextHandler;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 责任链的下一个对象</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setNextHandler</span><span class="params">(AbstractHandler nextHandler)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.nextHandler = nextHandler;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 具体参数拦截逻辑,给子类去实现</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">filter</span><span class="params">(Request request, Response response)</span> </span>&#123;</span><br><span class="line">        doFilter(request, response);</span><br><span class="line">        <span class="keyword">if</span> (getNextHandler() != <span class="keyword">null</span>) &#123;</span><br><span class="line">            getNextHandler().filter(request, response);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> AbstractHandler <span class="title">getNextHandler</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> nextHandler;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">     <span class="function"><span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">doFilter</span><span class="params">(Request filterRequest, Response response)</span></span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-3-2-每个对象差异化处理"><a href="#2-3-2-每个对象差异化处理" class="headerlink" title="2.3.2 每个对象差异化处理"></a>2.3.2 每个对象差异化处理</h4><p>责任链上，每个对象的<strong>差异化</strong>处理，如本小节的业务场景，就有参数校验对象、安全校验对象、黑名单校验对象、规则拦截对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Order(1)</span> <span class="comment">//顺序排第1，最先校验</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CheckParamFilterObject</span> <span class="keyword">extends</span> <span class="title">AbstractHandler</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">doFilter</span><span class="params">(Request request, Response response)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;非空参数检查&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  安全校验对象</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Order(2)</span> <span class="comment">//校验顺序排第2</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CheckSecurityFilterObject</span> <span class="keyword">extends</span> <span class="title">AbstractHandler</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">doFilter</span><span class="params">(Request request, Response response)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//invoke Security check</span></span><br><span class="line">        System.out.println(<span class="string">&quot;安全调用校验&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  黑名单校验对象</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Order(3)</span> <span class="comment">//校验顺序排第3</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CheckBlackFilterObject</span> <span class="keyword">extends</span> <span class="title">AbstractHandler</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">doFilter</span><span class="params">(Request request, Response response)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//invoke black list check</span></span><br><span class="line">        System.out.println(<span class="string">&quot;校验黑名单&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  规则拦截对象</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Order(4)</span> <span class="comment">//校验顺序排第4</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CheckRuleFilterObject</span> <span class="keyword">extends</span> <span class="title">AbstractHandler</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">doFilter</span><span class="params">(Request request, Response response)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//check rule</span></span><br><span class="line">        System.out.println(<span class="string">&quot;check rule&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-3-3-对象链连起来（初始化）-amp-amp-使用"><a href="#2-3-3-对象链连起来（初始化）-amp-amp-使用" class="headerlink" title="2.3.3 对象链连起来（初始化）&amp;&amp; 使用"></a>2.3.3 对象链连起来（初始化）&amp;&amp; 使用</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component(&quot;ChainPatternDemo&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ChainPatternDemo</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//自动注入各个责任链的对象</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> List&lt;AbstractHandler&gt; abstractHandleList;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> AbstractHandler abstractHandler;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//spring注入后自动执行，责任链的对象连接起来</span></span><br><span class="line">    <span class="meta">@PostConstruct</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">initializeChainFilter</span><span class="params">()</span></span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>;i&lt;abstractHandleList.size();i++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(i == <span class="number">0</span>)&#123;</span><br><span class="line">                abstractHandler = abstractHandleList.get(<span class="number">0</span>);</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                AbstractHandler currentHander = abstractHandleList.get(i - <span class="number">1</span>);</span><br><span class="line">                AbstractHandler nextHander = abstractHandleList.get(i);</span><br><span class="line">                currentHander.setNextHandler(nextHander);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//直接调用这个方法使用</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Response <span class="title">exec</span><span class="params">(Request request, Response response)</span> </span>&#123;</span><br><span class="line">        abstractHandler.filter(request, response);</span><br><span class="line">        <span class="keyword">return</span> response;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> AbstractHandler <span class="title">getAbstractHandler</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> abstractHandler;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAbstractHandler</span><span class="params">(AbstractHandler abstractHandler)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.abstractHandler = abstractHandler;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>运行结果如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">非空参数检查</span><br><span class="line">安全调用校验</span><br><span class="line">校验黑名单</span><br><span class="line">check rule</span><br></pre></td></tr></table></figure>

<blockquote>
<h4 id="模板方法模式"><a href="#模板方法模式" class="headerlink" title="模板方法模式"></a>模板方法模式</h4></blockquote>
<h3 id="3-1-业务场景"><a href="#3-1-业务场景" class="headerlink" title="3.1 业务场景"></a>3.1 业务场景</h3><p>假设我们有这么一个业务场景：内部系统不同商户，调用我们系统接口，去跟外部第三方系统交互（http方式）。走类似这么一个流程，如下：</p>
<p><img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211229191201437.png" alt="image-20211229191201437"></p>
<p>一个请求都会经历这几个流程：</p>
<ul>
<li>查询商户信息</li>
<li>对请求报文加签</li>
<li>发送http请求出去</li>
<li>对返回的报文验签</li>
</ul>
<p>这里，有的商户可能是走代理出去的，有的是走直连。假设当前有A，B商户接入，不少伙伴可能这么实现，伪代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 商户A处理句柄</span></span><br><span class="line">CompanyAHandler implements RequestHandler &#123;</span><br><span class="line">   <span class="function">Resp <span class="title">hander</span><span class="params">(req)</span></span>&#123;</span><br><span class="line">   <span class="comment">//查询商户信息</span></span><br><span class="line">   queryMerchantInfo();</span><br><span class="line">   <span class="comment">//加签</span></span><br><span class="line">   signature();</span><br><span class="line">   <span class="comment">//http请求（A商户假设走的是代理）</span></span><br><span class="line">   httpRequestbyProxy()</span><br><span class="line">   <span class="comment">//验签</span></span><br><span class="line">   verify();</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 商户B处理句柄</span></span><br><span class="line">CompanyBHandler implements RequestHandler &#123;</span><br><span class="line">   <span class="function">Resp <span class="title">hander</span><span class="params">(Rreq)</span></span>&#123;</span><br><span class="line">   <span class="comment">//查询商户信息</span></span><br><span class="line">   queryMerchantInfo();</span><br><span class="line">   <span class="comment">//加签</span></span><br><span class="line">   signature();</span><br><span class="line">   <span class="comment">// http请求（B商户不走代理，直连）</span></span><br><span class="line">   httpRequestbyDirect();</span><br><span class="line">   <span class="comment">// 验签</span></span><br><span class="line">   verify(); </span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>假设新加一个C商户接入，你需要再实现一套这样的代码。显然，这样代码就<strong>重复</strong>了，<strong>一些通用的方法，却在每一个子类都重新写了这一方法</strong>。</p>
<p>如何优化呢？可以使用<strong>模板方法模式</strong>。</p>
<h3 id="3-2-模板方法模式定义"><a href="#3-2-模板方法模式定义" class="headerlink" title="3.2 模板方法模式定义"></a>3.2 模板方法模式定义</h3><p>定义一个操作中的算法的骨架流程，而将一些步骤延迟到子类中，使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。它的核心思想就是：定义一个操作的一系列步骤，对于某些暂时确定不下来的步骤，就留给子类去实现，这样不同的子类就可以定义出不同的步骤。</p>
<h3 id="3-3-模板方法使用"><a href="#3-3-模板方法使用" class="headerlink" title="3.3 模板方法使用"></a>3.3 模板方法使用</h3><ul>
<li>一个抽象类，定义骨架流程（抽象方法放一起）</li>
<li>确定的共同方法步骤，放到抽象类（去除抽象方法标记）</li>
<li>不确定的步骤，给子类去差异化实现</li>
</ul>
<p>我们继续那以上的举例的业务流程例子，来一起用 模板方法优化一下哈：</p>
<h4 id="3-3-1-一个抽象类，定义骨架流程"><a href="#3-3-1-一个抽象类，定义骨架流程" class="headerlink" title="3.3.1 一个抽象类，定义骨架流程"></a>3.3.1 一个抽象类，定义骨架流程</h4><p>因为一个个请求经过的流程为一下步骤：</p>
<ul>
<li>查询商户信息</li>
<li>对请求报文加签</li>
<li>发送http请求出去</li>
<li>对返回的报文验签</li>
</ul>
<p>所以我们就可以定义一个抽象类，包含请求流程的几个方法，方法首先都定义为抽象方法哈：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 抽象类定义骨架流程（查询商户信息，加签，http请求，验签）</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">AbstractMerchantService</span>  </span>&#123; </span><br><span class="line"></span><br><span class="line">      <span class="comment">//查询商户信息</span></span><br><span class="line">      <span class="function"><span class="keyword">abstract</span> <span class="title">queryMerchantInfo</span><span class="params">()</span></span>;</span><br><span class="line">      <span class="comment">//加签</span></span><br><span class="line">      <span class="function"><span class="keyword">abstract</span> <span class="title">signature</span><span class="params">()</span></span>;</span><br><span class="line">      <span class="comment">//http 请求</span></span><br><span class="line">      <span class="function"><span class="keyword">abstract</span> <span class="title">httpRequest</span><span class="params">()</span></span>;</span><br><span class="line">       <span class="comment">// 验签</span></span><br><span class="line">       <span class="function"><span class="keyword">abstract</span> <span class="title">verifySinature</span><span class="params">()</span></span>;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="3-3-2-确定的共同方法步骤，放到抽象类"><a href="#3-3-2-确定的共同方法步骤，放到抽象类" class="headerlink" title="3.3.2 确定的共同方法步骤，放到抽象类"></a>3.3.2 确定的共同方法步骤，放到抽象类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">AbstractMerchantService</span>  </span>&#123; </span><br><span class="line"></span><br><span class="line">     <span class="comment">//模板方法流程</span></span><br><span class="line">     <span class="function">Resp <span class="title">handlerTempPlate</span><span class="params">(req)</span></span>&#123;</span><br><span class="line">           <span class="comment">//查询商户信息</span></span><br><span class="line">           queryMerchantInfo();</span><br><span class="line">           <span class="comment">//加签</span></span><br><span class="line">           signature();</span><br><span class="line">           <span class="comment">//http 请求</span></span><br><span class="line">           httpRequest();</span><br><span class="line">           <span class="comment">// 验签</span></span><br><span class="line">           verifySinature();</span><br><span class="line">     &#125;</span><br><span class="line">      <span class="comment">// Http是否走代理（提供给子类实现）</span></span><br><span class="line">      <span class="function"><span class="keyword">abstract</span> <span class="keyword">boolean</span> <span class="title">isRequestByProxy</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="3-3-3-不确定的步骤，给子类去差异化实现"><a href="#3-3-3-不确定的步骤，给子类去差异化实现" class="headerlink" title="3.3.3 不确定的步骤，给子类去差异化实现"></a>3.3.3 不确定的步骤，给子类去差异化实现</h4><p>因为是否走代理流程是<strong>不确定</strong>的，所以给子类去实现。</p>
<p>商户A的请求实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">CompanyAServiceImpl extends AbstractMerchantService&#123;</span><br><span class="line">    <span class="function">Resp <span class="title">hander</span><span class="params">(req)</span></span>&#123;</span><br><span class="line">      <span class="keyword">return</span> handlerTempPlate(req);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//走http代理的</span></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">isRequestByProxy</span><span class="params">()</span></span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>商户B的请求实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">CompanyBServiceImpl extends AbstractMerchantService&#123;</span><br><span class="line">    <span class="function">Resp <span class="title">hander</span><span class="params">(req)</span></span>&#123;</span><br><span class="line">      <span class="keyword">return</span> handlerTempPlate(req);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//公司B是不走代理的</span></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">isRequestByProxy</span><span class="params">()</span></span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<h4 id="4-观察者模式"><a href="#4-观察者模式" class="headerlink" title="4.观察者模式"></a>4.观察者模式</h4></blockquote>
<h3 id="4-1-业务场景"><a href="#4-1-业务场景" class="headerlink" title="4.1 业务场景"></a>4.1 业务场景</h3><p>登陆注册应该是最常见的业务场景了。就拿<strong>注册</strong>来说事，我们经常会遇到类似的场景，就是用户注册成功后，我们给用户发一条消息，又或者发个邮件等等，因此经常有如下的代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">register</span><span class="params">(User user)</span></span>&#123;</span><br><span class="line">  insertRegisterUser（user）;</span><br><span class="line">  sendIMMessage();</span><br><span class="line">  sendEmail()；</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这块代码会有什么问题呢？如果产品又加需求：现在注册成功的用户，再给用户发一条短信通知。于是你又得改register方法的代码了。。。这是不是违反了<strong>开闭原则</strong>啦。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">register</span><span class="params">(User user)</span></span>&#123;</span><br><span class="line">  insertRegisterUser（user）;</span><br><span class="line">  sendIMMessage();</span><br><span class="line">  sendMobileMessage（）;</span><br><span class="line">  sendEmail()；</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>并且，如果调<strong>发短信的接口失败</strong>了，是不是又影响到用户注册了？！这时候，是不是得加个异步方法给<strong>通知消息</strong>才好。。。</p>
<p>实际上，我们可以使用观察者模式优化。</p>
<h3 id="4-2-观察者模式定义"><a href="#4-2-观察者模式定义" class="headerlink" title="4.2 观察者模式定义"></a>4.2 观察者模式定义</h3><blockquote>
<p>观察者模式定义对象间的一种一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并被完成业务的更新。</p>
</blockquote>
<p>观察者模式属于行为模式，一个对象（被观察者）的状态发生改变，所有的依赖对象（观察者对象）都将得到通知，进行广播通知。它的主要成员就是<strong>观察者和被观察者</strong>。</p>
<ul>
<li>被观察者（Observerable）：目标对象，状态发生变化时，将通知所有的观察者。</li>
<li>观察者（observer）：接受被观察者的状态变化通知，执行预先定义的业务。</li>
</ul>
<p><strong>使用场景：</strong> 完成某件事情后，异步通知场景。如，登陆成功，发个IM消息等等。</p>
<h3 id="4-3-观察者模式使用"><a href="#4-3-观察者模式使用" class="headerlink" title="4.3 观察者模式使用"></a>4.3 观察者模式使用</h3><p>观察者模式实现的话，还是比较简单的。</p>
<ul>
<li>一个被观察者的类Observerable ;</li>
<li>多个观察者Observer ；</li>
<li>观察者的差异化实现</li>
<li>经典观察者模式封装：EventBus实战</li>
</ul>
<h4 id="4-3-1-一个被观察者的类Observerable-和-多个观察者Observer"><a href="#4-3-1-一个被观察者的类Observerable-和-多个观察者Observer" class="headerlink" title="4.3.1 一个被观察者的类Observerable 和 多个观察者Observer"></a>4.3.1 一个被观察者的类Observerable 和 多个观察者Observer</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Observerable</span> </span>&#123;</span><br><span class="line">   </span><br><span class="line">   <span class="keyword">private</span> List&lt;Observer&gt; observers </span><br><span class="line">      = <span class="keyword">new</span> ArrayList&lt;Observer&gt;();</span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">int</span> state;</span><br><span class="line"> </span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getState</span><span class="params">()</span> </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> state;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setState</span><span class="params">(<span class="keyword">int</span> state)</span> </span>&#123;</span><br><span class="line">      notifyAllObservers();</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="comment">//添加观察者</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addServer</span><span class="params">(Observer observer)</span></span>&#123;</span><br><span class="line">      observers.add(observer);      </span><br><span class="line">   &#125;</span><br><span class="line">   </span><br><span class="line">   <span class="comment">//移除观察者</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">removeServer</span><span class="params">(Observer observer)</span></span>&#123;</span><br><span class="line">      observers.remove(observer);      </span><br><span class="line">   &#125;</span><br><span class="line">   <span class="comment">//通知</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">notifyAllObservers</span><span class="params">(<span class="keyword">int</span> state)</span></span>&#123;</span><br><span class="line">      <span class="keyword">if</span>(state!=<span class="number">1</span>)&#123;</span><br><span class="line">          System.out.println(“不是通知的状态”);</span><br><span class="line">         <span class="keyword">return</span> ;</span><br><span class="line">      &#125;</span><br><span class="line">   </span><br><span class="line">      <span class="keyword">for</span> (Observer observer : observers) &#123;</span><br><span class="line">         observer.doEvent();</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="4-3-2-观察者的差异化实现"><a href="#4-3-2-观察者的差异化实现" class="headerlink" title="4.3.2 观察者的差异化实现"></a>4.3.2 观察者的差异化实现</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment">//观察者</span></span><br><span class="line"> <span class="class"><span class="keyword">interface</span> <span class="title">Observer</span> </span>&#123;  </span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">doEvent</span><span class="params">()</span></span>;  </span><br><span class="line">&#125;  </span><br><span class="line"><span class="comment">//Im消息</span></span><br><span class="line">IMMessageObserver implements Observer&#123;</span><br><span class="line">    <span class="keyword">void</span> doEvent（）&#123;</span><br><span class="line">       System.out.println(<span class="string">&quot;发送IM消息&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//手机短信</span></span><br><span class="line">MobileNoObserver implements Observer&#123;</span><br><span class="line">    <span class="keyword">void</span> doEvent（）&#123;</span><br><span class="line">       System.out.println(<span class="string">&quot;发送短信消息&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//EmailNo</span></span><br><span class="line">EmailObserver implements Observer&#123;</span><br><span class="line">    <span class="keyword">void</span> doEvent（）&#123;</span><br><span class="line">       System.out.println(<span class="string">&quot;发送email消息&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="4-3-3-EventBus实战"><a href="#4-3-3-EventBus实战" class="headerlink" title="4.3.3 EventBus实战"></a>4.3.3 EventBus实战</h4><p>自己搞一套观察者模式的代码，还是有点小麻烦。实际上，<code>Guava EventBus</code>就封装好了，它 提供一套基于注解的事件总线，api可以灵活的使用，爽歪歪。</p>
<p>我们来看下<code>EventBus</code>的实战代码哈，首先可以声明一个EventBusCenter类，它类似于以上被观察者那种角色<code>Observerable</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EventBusCenter</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> EventBus eventBus = <span class="keyword">new</span> EventBus();</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">EventBusCenter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> EventBus <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> eventBus;</span><br><span class="line">    &#125;</span><br><span class="line">     <span class="comment">//添加观察者</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">register</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">        eventBus.register(obj);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//移除观察者</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">unregister</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">        eventBus.unregister(obj);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//把消息推给观察者</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">post</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">        eventBus.post(obj);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>然后再声明观察者<code>EventListener</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EventListener</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Subscribe</span> <span class="comment">//加了订阅，这里标记这个方法是事件处理方法  </span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handle</span><span class="params">(NotifyEvent notifyEvent)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;发送IM消息&quot;</span> + notifyEvent.getImNo());</span><br><span class="line">        System.out.println(<span class="string">&quot;发送短信消息&quot;</span> + notifyEvent.getMobileNo());</span><br><span class="line">        System.out.println(<span class="string">&quot;发送Email消息&quot;</span> + notifyEvent.getEmailNo());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//通知事件类</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">NotifyEvent</span>  </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String mobileNo;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String emailNo;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String imNo;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">NotifyEvent</span><span class="params">(String mobileNo, String emailNo, String imNo)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.mobileNo = mobileNo;</span><br><span class="line">        <span class="keyword">this</span>.emailNo = emailNo;</span><br><span class="line">        <span class="keyword">this</span>.imNo = imNo;</span><br><span class="line">    &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>使用demo测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EventBusDemoTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        EventListener eventListener = <span class="keyword">new</span> EventListener();</span><br><span class="line">        EventBusCenter.register(eventListener);</span><br><span class="line">        EventBusCenter.post(<span class="keyword">new</span> NotifyEvent(<span class="string">&quot;13372817283&quot;</span>, <span class="string">&quot;123@qq.com&quot;</span>, <span class="string">&quot;666&quot;</span>));</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">发送IM消息<span class="number">666</span></span><br><span class="line">发送短信消息<span class="number">13372817283</span></span><br><span class="line">发送Email消息<span class="number">123</span><span class="meta">@qq</span>.com</span><br></pre></td></tr></table></figure>

<blockquote>
<h4 id="5-工厂模式"><a href="#5-工厂模式" class="headerlink" title="5.工厂模式"></a>5.工厂模式</h4></blockquote>
<h3 id="5-1-业务场景"><a href="#5-1-业务场景" class="headerlink" title="5.1 业务场景"></a>5.1 业务场景</h3><p>工厂模式一般配合策略模式一起使用。用来去优化大量的<code>if...else...</code>或<code>switch...case...</code>条件语句。</p>
<p>我们就取第一小节中策略模式那个例子吧。根据不同的文件解析类型，创建不同的解析对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">IFileStrategy <span class="title">getFileStrategy</span><span class="params">(FileTypeResolveEnum fileType)</span></span>&#123;</span><br><span class="line">     IFileStrategy  fileStrategy ;</span><br><span class="line">     <span class="keyword">if</span>(fileType=FileTypeResolveEnum.File_A_RESOLVE)&#123;</span><br><span class="line">       fileStrategy = <span class="keyword">new</span> AFileResolve();</span><br><span class="line">     &#125;<span class="keyword">else</span> <span class="keyword">if</span>(fileType=FileTypeResolveEnum.File_A_RESOLV)&#123;</span><br><span class="line">       fileStrategy = <span class="keyword">new</span> BFileResolve();</span><br><span class="line">     &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">       fileStrategy = <span class="keyword">new</span> DefaultFileResolve();</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="keyword">return</span> fileStrategy;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>其实这就是<strong>工厂模式</strong>，定义一个创建对象的接口，让其子类自己决定实例化哪一个工厂类，工厂模式使其创建过程延迟到子类进行。</p>
<p>策略模式的例子，没有使用上一段代码，而是借助spring的特性，搞了一个工厂模式，哈哈，小伙伴们可以回去那个例子细品一下，我把代码再搬下来，小伙伴们再品一下吧：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StrategyUseService</span> <span class="keyword">implements</span> <span class="title">ApplicationContextAware</span></span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Map&lt;FileTypeResolveEnum, IFileStrategy&gt; iFileStrategyMap = <span class="keyword">new</span> ConcurrentHashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//把所有的文件类型解析的对象，放到map，需要使用时，信手拈来即可。这就是工厂模式的一种体现啦</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setApplicationContext</span><span class="params">(ApplicationContext applicationContext)</span> <span class="keyword">throws</span> BeansException </span>&#123;</span><br><span class="line">        Map&lt;String, IFileStrategy&gt; tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);</span><br><span class="line">        tmepMap.values().forEach(strategyService -&gt; iFileStrategyMap.put(strategyService.gainFileType(), strategyService));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="5-2-使用工厂模式"><a href="#5-2-使用工厂模式" class="headerlink" title="5.2 使用工厂模式"></a>5.2 使用工厂模式</h3><p>定义工厂模式也是比较简单的:</p>
<ul>
<li>一个工厂接口，提供一个创建不同对象的方法。</li>
<li>其子类实现工厂接口，构造不同对象</li>
<li>使用工厂模式</li>
</ul>
<h4 id="5-3-1-一个工厂接口"><a href="#5-3-1-一个工厂接口" class="headerlink" title="5.3.1 一个工厂接口"></a>5.3.1 一个工厂接口</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">IFileResolveFactory</span></span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">resolve</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="5-3-2-不同子类实现工厂接口"><a href="#5-3-2-不同子类实现工厂接口" class="headerlink" title="5.3.2 不同子类实现工厂接口"></a>5.3.2 不同子类实现工厂接口</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AFileResolve</span> <span class="keyword">implements</span> <span class="title">IFileResolveFactory</span></span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">resolve</span><span class="params">()</span></span>&#123;</span><br><span class="line">      System.out.println(<span class="string">&quot;文件A类型解析&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BFileResolve</span> <span class="keyword">implements</span> <span class="title">IFileResolveFactory</span></span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">resolve</span><span class="params">()</span></span>&#123;</span><br><span class="line">      System.out.println(<span class="string">&quot;文件B类型解析&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DefaultFileResolve</span> <span class="keyword">implements</span> <span class="title">IFileResolveFactory</span></span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">resolve</span><span class="params">()</span></span>&#123;</span><br><span class="line">      System.out.println(<span class="string">&quot;默认文件类型解析&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="5-3-3-使用工厂模式"><a href="#5-3-3-使用工厂模式" class="headerlink" title="5.3.3 使用工厂模式"></a>5.3.3 使用工厂模式</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造不同的工厂对象</span></span><br><span class="line">IFileResolveFactory fileResolveFactory;</span><br><span class="line"><span class="keyword">if</span>(fileType=“A”)&#123;</span><br><span class="line">    fileResolveFactory = <span class="keyword">new</span> AFileResolve();</span><br><span class="line">&#125;<span class="keyword">else</span> <span class="keyword">if</span>(fileType=“B”)&#123;</span><br><span class="line">    fileResolveFactory = <span class="keyword">new</span> BFileResolve();</span><br><span class="line"> &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">    fileResolveFactory = <span class="keyword">new</span> DefaultFileResolve();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">fileResolveFactory.resolve();</span><br></pre></td></tr></table></figure>

<p>一般情况下，对于工厂模式，你不会看到以上的代码。工厂模式会跟配合其他设计模式如策略模式一起出现的。</p>
<blockquote>
<h4 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h4></blockquote>
<h3 id="6-1-业务场景"><a href="#6-1-业务场景" class="headerlink" title="6.1 业务场景"></a>6.1 业务场景</h3><p>单例模式，<strong>保证一个类仅有一个实例</strong>，并提供一个访问它的全局访问点。I/O与数据库的连接,一般就用单例模式实现de的。Windows里面的Task Manager（任务管理器）也是很典型的单例模式。</p>
<p>来看一个单例模式的例子</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LanHanSingleton</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> LanHanSingleton instance;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">LanHanSingleton</span><span class="params">()</span></span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> LanHanSingleton <span class="title">getInstance</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">            instance = <span class="keyword">new</span> LanHanSingleton();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"> </span><br></pre></td></tr></table></figure>

<p>以上的例子，就是<strong>懒汉式</strong>的单例实现。实例在需要用到的时候，才去创建，就比较懒。如果有则返回，没有则新建，需要加下 <code>synchronized</code>关键字，要不然可能存在<strong>线性安全问题</strong>。</p>
<h3 id="6-2-单例模式的经典写法"><a href="#6-2-单例模式的经典写法" class="headerlink" title="6.2 单例模式的经典写法"></a>6.2 单例模式的经典写法</h3><p>其实单例模式还有有好几种实现方式，如饿汉模式，双重校验锁，静态内部类，枚举等实现方式。</p>
<h4 id="6-2-1-饿汉模式"><a href="#6-2-1-饿汉模式" class="headerlink" title="6.2.1 饿汉模式"></a>6.2.1 饿汉模式</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EHanSingleton</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">static</span> EHanSingleton instance = <span class="keyword">new</span> EHanSingleton();</span><br><span class="line">   </span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="title">EHanSingleton</span><span class="params">()</span></span>&#123;      </span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> EHanSingleton <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> instance;</span><br><span class="line">   &#125;</span><br><span class="line">   </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>饿汉模式，它<strong>比较饥饿、比较勤奋</strong>，实例在初始化的时候就已经建好了，不管你后面有没有用到，都先新建好实例再说。这个就没有线程安全的问题，但是呢，浪费内存空间呀。</p>
<h4 id="6-2-2-双重校验锁"><a href="#6-2-2-双重校验锁" class="headerlink" title="6.2.2 双重校验锁"></a>6.2.2 双重校验锁</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DoubleCheckSingleton</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">static</span> DoubleCheckSingleton instance;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="title">DoubleCheckSingleton</span><span class="params">()</span> </span>&#123; &#125;</span><br><span class="line">   </span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> DoubleCheckSingleton <span class="title">getInstance</span><span class="params">()</span></span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">           <span class="keyword">synchronized</span> (DoubleCheckSingleton.class) &#123;</span><br><span class="line">               <span class="keyword">if</span> (instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">                   instance = <span class="keyword">new</span> DoubleCheckSingleton();</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> instance;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>双重校验锁实现的单例模式，综合了懒汉式和饿汉式两者的优缺点。以上代码例子中，在synchronized关键字内外都加了一层  <code>if</code>条件判断，这样既保证了线程安全，又比直接上锁提高了执行效率，还节省了内存空间。</p>
<h4 id="6-2-3-静态内部类"><a href="#6-2-3-静态内部类" class="headerlink" title="6.2.3 静态内部类"></a>6.2.3 静态内部类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">InnerClassSingleton</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">InnerClassSingletonHolder</span></span>&#123;</span><br><span class="line">       <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> InnerClassSingleton INSTANCE = <span class="keyword">new</span> InnerClassSingleton();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="title">InnerClassSingleton</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line">   </span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> InnerClassSingleton <span class="title">getInstance</span><span class="params">()</span></span>&#123;</span><br><span class="line">       <span class="keyword">return</span> InnerClassSingletonHolder.INSTANCE;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>静态内部类的实现方式，效果有点类似双重校验锁。但这种方式只适用于静态域场景，双重校验锁方式可在实例域需要延迟初始化时使用。</p>
<h4 id="6-2-4-枚举"><a href="#6-2-4-枚举" class="headerlink" title="6.2.4 枚举"></a>6.2.4 枚举</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">enum</span> <span class="title">SingletonEnum</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    INSTANCE;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> SingletonEnum <span class="title">getInstance</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> INSTANCE;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>枚举实现的单例，代码简洁清晰。并且它还自动支持序列化机制，绝对防止多次实例化。</p>

    </div>
<div>
  
    <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

  
</div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://wan-lei8.gitee.io/2020/12/29/%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E7%A7%8D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" title="常用的几种设计模式">https://wan-lei8.gitee.io/2020/12/29/常用的几种设计模式/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2020/12/21/%E5%A4%A7%E4%BA%8B%E5%8A%A1%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/" rel="prev" title="大事务解决方案">
      <i class="fa fa-chevron-left"></i> 大事务解决方案
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/08/15/WorkSummary-Collage-Table-Design/" rel="next" title="WorkSummary_Collage_Table_Design">
      WorkSummary_Collage_Table_Design <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.</span> <span class="nav-text">1.策略模式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%E5%AE%9A%E4%B9%89"><span class="nav-number"></span> <span class="nav-text">1.2 策略模式定义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%E4%BD%BF%E7%94%A8"><span class="nav-number"></span> <span class="nav-text">1.3 策略模式使用</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-3-1-%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%EF%BC%8C%E4%B8%A4%E4%B8%AA%E6%96%B9%E6%B3%95"><span class="nav-number">1.</span> <span class="nav-text">1.3.1 一个接口，两个方法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-3-2-%E4%B8%8D%E5%90%8C%E7%AD%96%E7%95%A5%E7%9A%84%E5%B7%AE%E5%BC%82%E5%8C%96%E5%AE%9E%E7%8E%B0"><span class="nav-number">2.</span> <span class="nav-text">1.3.2 不同策略的差异化实现</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-3-3-%E4%BD%BF%E7%94%A8%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F"><span class="nav-number">3.</span> <span class="nav-text">1.3.3 使用策略模式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F"><span class="nav-number">4.</span> <span class="nav-text">责任链模式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF"><span class="nav-number"></span> <span class="nav-text">2.1 业务场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F%E5%AE%9A%E4%B9%89"><span class="nav-number"></span> <span class="nav-text">2.2 责任链模式定义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F%E4%BD%BF%E7%94%A8"><span class="nav-number"></span> <span class="nav-text">2.3 责任链模式使用</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-1-%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%E6%88%96%E8%80%85%E6%8A%BD%E8%B1%A1%E7%B1%BB"><span class="nav-number">1.</span> <span class="nav-text">2.3.1 一个接口或者抽象类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-2-%E6%AF%8F%E4%B8%AA%E5%AF%B9%E8%B1%A1%E5%B7%AE%E5%BC%82%E5%8C%96%E5%A4%84%E7%90%86"><span class="nav-number">2.</span> <span class="nav-text">2.3.2 每个对象差异化处理</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-3-%E5%AF%B9%E8%B1%A1%E9%93%BE%E8%BF%9E%E8%B5%B7%E6%9D%A5%EF%BC%88%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%89-amp-amp-%E4%BD%BF%E7%94%A8"><span class="nav-number">3.</span> <span class="nav-text">2.3.3 对象链连起来（初始化）&amp;&amp; 使用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F"><span class="nav-number">4.</span> <span class="nav-text">模板方法模式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF"><span class="nav-number"></span> <span class="nav-text">3.1 业务场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F%E5%AE%9A%E4%B9%89"><span class="nav-number"></span> <span class="nav-text">3.2 模板方法模式定义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-3-%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8"><span class="nav-number"></span> <span class="nav-text">3.3 模板方法使用</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-1-%E4%B8%80%E4%B8%AA%E6%8A%BD%E8%B1%A1%E7%B1%BB%EF%BC%8C%E5%AE%9A%E4%B9%89%E9%AA%A8%E6%9E%B6%E6%B5%81%E7%A8%8B"><span class="nav-number">1.</span> <span class="nav-text">3.3.1 一个抽象类，定义骨架流程</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-2-%E7%A1%AE%E5%AE%9A%E7%9A%84%E5%85%B1%E5%90%8C%E6%96%B9%E6%B3%95%E6%AD%A5%E9%AA%A4%EF%BC%8C%E6%94%BE%E5%88%B0%E6%8A%BD%E8%B1%A1%E7%B1%BB"><span class="nav-number">2.</span> <span class="nav-text">3.3.2 确定的共同方法步骤，放到抽象类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-3-%E4%B8%8D%E7%A1%AE%E5%AE%9A%E7%9A%84%E6%AD%A5%E9%AA%A4%EF%BC%8C%E7%BB%99%E5%AD%90%E7%B1%BB%E5%8E%BB%E5%B7%AE%E5%BC%82%E5%8C%96%E5%AE%9E%E7%8E%B0"><span class="nav-number">3.</span> <span class="nav-text">3.3.3 不确定的步骤，给子类去差异化实现</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F"><span class="nav-number">4.</span> <span class="nav-text">4.观察者模式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-1-%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF"><span class="nav-number"></span> <span class="nav-text">4.1 业务场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F%E5%AE%9A%E4%B9%89"><span class="nav-number"></span> <span class="nav-text">4.2 观察者模式定义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-3-%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F%E4%BD%BF%E7%94%A8"><span class="nav-number"></span> <span class="nav-text">4.3 观察者模式使用</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-3-1-%E4%B8%80%E4%B8%AA%E8%A2%AB%E8%A7%82%E5%AF%9F%E8%80%85%E7%9A%84%E7%B1%BBObserverable-%E5%92%8C-%E5%A4%9A%E4%B8%AA%E8%A7%82%E5%AF%9F%E8%80%85Observer"><span class="nav-number">1.</span> <span class="nav-text">4.3.1 一个被观察者的类Observerable 和 多个观察者Observer</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-3-2-%E8%A7%82%E5%AF%9F%E8%80%85%E7%9A%84%E5%B7%AE%E5%BC%82%E5%8C%96%E5%AE%9E%E7%8E%B0"><span class="nav-number">2.</span> <span class="nav-text">4.3.2 观察者的差异化实现</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-3-3-EventBus%E5%AE%9E%E6%88%98"><span class="nav-number">3.</span> <span class="nav-text">4.3.3 EventBus实战</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F"><span class="nav-number">4.</span> <span class="nav-text">5.工厂模式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-1-%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF"><span class="nav-number"></span> <span class="nav-text">5.1 业务场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-2-%E4%BD%BF%E7%94%A8%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F"><span class="nav-number"></span> <span class="nav-text">5.2 使用工厂模式</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#5-3-1-%E4%B8%80%E4%B8%AA%E5%B7%A5%E5%8E%82%E6%8E%A5%E5%8F%A3"><span class="nav-number">1.</span> <span class="nav-text">5.3.1 一个工厂接口</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-3-2-%E4%B8%8D%E5%90%8C%E5%AD%90%E7%B1%BB%E5%AE%9E%E7%8E%B0%E5%B7%A5%E5%8E%82%E6%8E%A5%E5%8F%A3"><span class="nav-number">2.</span> <span class="nav-text">5.3.2 不同子类实现工厂接口</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-3-3-%E4%BD%BF%E7%94%A8%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F"><span class="nav-number"></span> <span class="nav-text">5.3.3 使用工厂模式</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.</span> <span class="nav-text">单例模式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6-1-%E4%B8%9A%E5%8A%A1%E5%9C%BA%E6%99%AF"><span class="nav-number"></span> <span class="nav-text">6.1 业务场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6-2-%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E7%9A%84%E7%BB%8F%E5%85%B8%E5%86%99%E6%B3%95"><span class="nav-number"></span> <span class="nav-text">6.2 单例模式的经典写法</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#6-2-1-%E9%A5%BF%E6%B1%89%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.</span> <span class="nav-text">6.2.1 饿汉模式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#6-2-2-%E5%8F%8C%E9%87%8D%E6%A0%A1%E9%AA%8C%E9%94%81"><span class="nav-number">2.</span> <span class="nav-text">6.2.2 双重校验锁</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#6-2-3-%E9%9D%99%E6%80%81%E5%86%85%E9%83%A8%E7%B1%BB"><span class="nav-number">3.</span> <span class="nav-text">6.2.3 静态内部类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#6-2-4-%E6%9E%9A%E4%B8%BE"><span class="nav-number">4.</span> <span class="nav-text">6.2.4 枚举</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt=""
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name"></p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives">
          <span class="site-state-item-count">41</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/yourname" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;yourname" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="/malegod958@163.com" title="E-Mail → malegod958@163.com"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2018 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">万磊</span>
</div>
  <div class="powered-by">

  </div>

        








      </div>
    </footer>
  </div>

  
  
  <script color='' opacity='0.5' zIndex='-1' count='99' src="/lib/canvas-nest/canvas-nest.min.js"></script>
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

  
	<script type="text/javascript" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>
	

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/src/clicklove.js"></script>
